package com.project.easy.common.util.date;

import com.project.easy.common.util.constants.CommonConstant;
import com.project.easy.common.util.exception.print.PrintException;
import com.project.easy.common.util.string.StringUtil;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.project.easy.common.util.constants.CommonConstant.YMDHMS;

/**
 * @ClassName DateTool
 * @Description
 * @Author GreatorMan.cool
 * @Date 2021/3/25 16:30
 * @Version 1.0
 **/
public final class DateTool {
    /**
     * 私有构成函数
     */
    private  DateTool() { }


    private static String ymd = "yyyy-MM-dd";
    private static SimpleDateFormat ymdSDF = new SimpleDateFormat(ymd);
    private static String year = "yyyy";
    private static String month = "MM";
    private static String day = "dd";
    private static SimpleDateFormat yyyyMMddHHmmss = new SimpleDateFormat(YMDHMS);
    private static SimpleDateFormat yearSDF = new SimpleDateFormat(year);
    private static SimpleDateFormat monthSDF = new SimpleDateFormat(month);
    private static SimpleDateFormat daySDF = new SimpleDateFormat(day);
    private static SimpleDateFormat yyyyMMddHHmm = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    private static SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyy-MM-dd");
    private static final long DATEMM = 86400L;

    public static SimpleDateFormat getYyyyMMdd() {
        return yyyyMMdd;
    }
    /**
     * 加月份
     * @param date 时间
     * @param months 加月
     * @return 返回计算好的时间
     */
    public static Date addMonths(Date date, int months) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.MONTH, months);
        return c.getTime();
    }
    /**
     * 获取年月日(字符串类型)
     * 格式：2014-12-02
     * @param date 时间
     * @return 返回时间
     */
    public  static  Date getDayByDate(Date date) {
        try {
            return  DateTool.parseStringToDate(ymdSDF.format(date), ymd);
        } catch (Exception e) {
            PrintException.print(e);
        }
        return  date;
    }
    /**
     *新增日期天
     * @param date 时间
     * @param day 天
     * @return 返回时间
     */
    public static Date  addDay(Date date, Integer day) {
        if (Objects.isNull(date)) {
            date = new Date();
        }
        if (Objects.isNull(day)) {
            day = 1;
        }
        Calendar nowTime = Calendar.getInstance();
        nowTime.setTime(date);
        nowTime.add(Calendar.DAY_OF_YEAR, day);
        return nowTime.getTime();
    }
    /**
     * 获取时间字符串
     * @param date  时间
     * @param pattern 返回时间格式
     * @return 返回字符串格式 yyyy-MM-dd HH:mm:ss
     */
    public static String getStringDate(Date date, String pattern) {
        if (null == date) {
            date = new Date();
        }
        if (StringUtil.isBlank(pattern)) {
            pattern = YMDHMS;
        }
        SimpleDateFormat formatter = new SimpleDateFormat(pattern);
        String dateString = formatter.format(date);
        return dateString;
    }

    /**
     * @return 返回时间
     */
    public static Date getCurrentTime() {
        return new Date();
    }
    /**
     * 获得当前时间(字符串类型)
     * 格式：2014-12-02 10:38:53
     * @return String
     */
    public static String getCurrentTimeStr() {
        return yyyyMMddHHmmss.format(getCurrentDate());
    }
    /**
     * 时间新增分钟
     * @param date 时间
     * @param mul 分钟
     * @return 返回时间
     */
    public static Date  addMul(Date date, Integer mul) {
        if (Objects.isNull(date)) {
            date = new Date();
        }
        if (Objects.isNull(mul)) {
            mul = 1;
        }
        Calendar nowTime = Calendar.getInstance();
        nowTime.setTime(date);
        nowTime.add(Calendar.MINUTE, mul);
        return nowTime.getTime();
    }
    /**
     * 获取年月日(日期类型)
     * 格式：2014-12-02
     * @return String
     */
    public static Date getDate() {
        return DateTool.parseStringToDate(getCurrentTimeStr(), ymd);
    }
    /**
     * 获取年月日(字符串类型)
     * 格式：2014-12-02
     * @return String
     */
    public static String getCurrentDate() {
        return ymdSDF.format(new Date());
    }
    /**
     * 可以获取昨天的日期
     * 格式：2014-12-01
     * @return 返回时间
     */
    public static String getYesterdayYYYYMMDD() {
        Date date = new Date(System.currentTimeMillis() - DATEMM * 1000L);
        String str = yyyyMMdd.format(date);
        try {
            date = yyyyMMddHHmmss.parse(str + " 00:00:00");
            return yyyyMMdd.format(date);
        } catch (ParseException e) {
            PrintException.print(e);
        }
        return "";
    }
    /**
     * 获取当前的年
     * @return String 年
     */
    public static String getCurrentYear() {
        return yearSDF.format(new Date());
    }
    /**
     * 获取当前月
     * @return 返回月
     */
    public static String getCurrentMonth() {
        return monthSDF.format(new Date());
    }
    /**
     * 获取数据天
     * @return 返回天
     */
    public static String getCurrentDay() {
        return daySDF.format(new Date());
    }
    /**
     * 获取今天0点开始的秒数
     * @return long
     */
    public static long getTimeNumberToday() {
        Date date = new Date();
        String str = yyyyMMdd.format(date);
        try {
            date = yyyyMMdd.parse(str);
            return date.getTime() / 1000L;
        } catch (ParseException e) {
            PrintException.print(e);
        }
        return 0L;
    }
    /**
     * 获得昨天零点
     * @return Date
     */
    public static Date getYesterDayZeroHour() {
        return  addDay(new Date(getTimeNumberToday()), -1);
    }
    /**
     * 把long型日期转String ；---OK
     * @param date   long型日期；
     * @param format 日期格式；
     * @return 返回时间格式
     */
    public static String longToString(long date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        // 前面的lSysTime是秒数，先乘1000得到毫秒数，再转为java.util.Date类型
        Date dt2 = new Date(date * 1000L);
        String sDateTime = sdf.format(dt2); // 得到精确到秒的表示：08/31/2006 21:08:00
        return sDateTime;
    }
    /**
     * 获得今天零点
     * @return Date时间
     */
    public static Date getTodayZeroHour() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.HOUR, 0);
        return cal.getTime();
    }
    /**
     * 获得昨天23时59分59秒
     * @return 昨天的时间
     */
    public static Date getHour() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, 0);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.HOUR, 23);
        return cal.getTime();
    }
    /**
     * 获取时间 周几
     * @param date 时间
     * @return 周几
     */
    public static Integer getWeek(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.DAY_OF_WEEK) - 1;
    }
    /**
     * 字符串转换为时间
     * @param date   待转换的字符串型日期；
     * @param format 转化的日期格式
     * @return 返回该字符串的日期型数据, 异常返回Null
     */
    public static Date parseStringToDate(String date, String format)  {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            sdf.setLenient(false);
            return sdf.parse(date);
        } catch (ParseException e) {
            PrintException.print(e);
            return null;
        }
    }
     /**
     * 获得指定日期所在的自然周的第一天，即周日
     * @param date 日期
     * @return 自然周的第一天
     */
    public static Date getStartDayOfWeek(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.DAY_OF_WEEK, 1);
        date = c.getTime();
        return date;
    }
    /**
     * 获得指定日期所在的自然周的最后一天，即周六
     * @param date 时间
     * @return 返回时间的周六
     */
    public static Date getLastDayOfWeek(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.DAY_OF_WEEK, 7);
        date = c.getTime();
        return date;
    }
    /**
     * 获得指定日期所在当月第一天
     * @param date 时间
     * @return 返回时间
     */
    public static Date getStartDayOfMonth(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.DAY_OF_MONTH, 1);
        date = c.getTime();
        return date;
    }
    /**
     * 获得指定日期所在当月最后一天
     * @param date 时间
     * @return 返回时间
     */
    public static Date getLastDayOfMonth(Date date) {
        Calendar instance = Calendar.getInstance();
        instance.setTime(date);
        instance.set(Calendar.DATE, 1);
        instance.add(Calendar.MONTH, 1);
        instance.add(Calendar.DATE, -1);
        date = instance.getTime();
        return date;
    }
    /**
     * 获得指定日期的下一个月的第一天
     * @param date 时间
     * @return 返回时间
     */
    public static Date getStartDayOfNextMonth(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.MONTH, 1);
        c.set(Calendar.DAY_OF_MONTH, 1);
        date = c.getTime();
        return date;
    }
    /**
     * 获得指定日期的下一个月的最后一天
     * @param date 时间
     * @return 返回时间
     */
    public static Date getLastDayOfNextMonth(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.DATE, 1);
        c.add(Calendar.MONTH, 2);
        c.add(Calendar.DATE, -1);
        date = c.getTime();
        return date;
    }
    /**
     * 把String 日期转换成long型日期；
     * @param date   String 型日期；
     * @param format 日期格式；
     * @return 时间分钟
     */
    public static long convertStringToLong(String date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date dt2 = null;
        long lTime = 0;
        try {
            dt2 = sdf.parse(date);
            // 继续转换得到秒数的long型
            lTime = dt2.getTime() / 1000;
        } catch (ParseException e) {
            PrintException.print(e);
        }
        return lTime;
    }
    /**
     * 得到二个日期间的间隔日期；
     * @param endTime   结束时间
     * @param beginTime 开始时间
     * @param isEndTime 是否包含结束日期；
     * @return 返回时间集合
     */
    public static Map<String, String> getTwoDay(String endTime,
                                                String beginTime, boolean isEndTime) {
        Map<String, String> result = new HashMap<String, String>();
        if (StringUtil.isBlank(endTime) || StringUtil.isBlank(beginTime)) {
            return CommonConstant.EMPTY_MAP;
        }
        try {
            Date date = ymdSDF.parse(endTime);
            endTime = ymdSDF.format(date);
            Date mydate = ymdSDF.parse(beginTime);
            long days = (date.getTime() - mydate.getTime())
                    / (24 * 60 * 60 * 1000);
            result = getDate(endTime, Integer.parseInt(days + ""), isEndTime);
        } catch (Exception e) {
            PrintException.print(e);
        }
        return result;
    }
    /**
     * 得到二个日期间的间隔日期；天
     * @param endTime   结束时间
     * @param beginTime 开始时间
     * @return 返回天
     */
    public static Integer getTwoDayInterval(String endTime, String beginTime) {
        if (StringUtil.isBlank(endTime) || StringUtil.isBlank(beginTime)) {
            return 0;
        }
        long days = 0L;
        try {
            Date date = ymdSDF.parse(endTime);
            Date mydate = ymdSDF.parse(beginTime);
            days = (date.getTime() - mydate.getTime()) / (24 * 60 * 60 * 1000);
        } catch (Exception e) {
            return 0;
        }
        return Integer.parseInt(days + "");
    }
    /**
     * 根据结束时间以及间隔差值，求符合要求的日期集合；
     * @param endTime 结束时间
     * @param interval 天
     * @param isEndTime 是否包含结束时间
     * @return 返回集合
     */
    public static Map<String, String> getDate(String endTime, Integer interval,
                                              boolean isEndTime) {
        Map<String, String> result = new HashMap<String, String>();
        if (interval == 0 || isEndTime) {
            if (isEndTime) {
                result.put(endTime, endTime);
            }
        }
        if (interval > 0) {
            Date date = DateTool.parseStringToDate(endTime, ymd);
            for (int i = 0; i < interval; i++) {
                if (!isEndTime && i == 0) {
                    continue;
                }
                endTime = DateTool.getStringDate(date, ymd);
                result.put(endTime, endTime);
            }
        }
        return result;
    }
    /**
     * 获取有效时间
     * @param date 当前时间
     * @param type 有效时间单位 SECOND / DAy..
     * @param times 有效时间
     * @return 返回时间
     */
    public static Date getExpiressTime(Date date, int type, int times) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(type, times);
        return calendar.getTime();
    }
    /**
     * 获取当日凌晨
     * @return 返回时间
     */
    public static Date getEarlyMorning() {
        String date = yyyyMMdd.format(new Date());
        Date start = null;
        try {
            start = yyyyMMddHHmmss.parse(date + " 00:00:00");
        } catch (ParseException e) {
            PrintException.print(e);
        }
        return start;
    }
    /**
     * 一个月的天数
     * @param date 时间
     * @return 返回天
     */
    public static  Integer getYearDay(Date date) {
        Calendar cal = Calendar.getInstance();
        return  cal.get(Calendar.DAY_OF_MONTH);
    }
    /**
     * 一年中的第几周
     * @param date 时间
     * @return 一年的第几周
     */
    public static Integer getYearWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setTime(date);
        return calendar.get(Calendar.WEEK_OF_YEAR);
    }
    /**
     * 时间一年的第几月
     * @param date 时间
     * @return 返回月
     */
    public static Integer getYearMoth(Date date) {
        Calendar cal = Calendar.getInstance();
        int m = cal.get(Calendar.MONTH) + 1;
        return m;
    }
    /**
     * 　季度
     * @param date 时间
     * @return 返回季度
     */
    public static Integer getYearQuarter(Date date) {
        Integer m = getYearMoth(date);
        int quarter = 0;
        if (m >= 1 && m == 3) {
            quarter = 1;
        }
        if (m >= 4 && m <= 6) {
            quarter = 2;
        }
        if (m >= 7 && m <= 9) {
            quarter = 3;
        }
        if (m >= 10 && m <= 12) {
            quarter = 4;
        }
        return quarter;
    }
    /**
     * 获取当日结束时间
     * @return 返回时间
     */
    public static Date getEarlyNight() {
        try {
            return yyyyMMddHHmmss.parse(String.format("%s 23:59:59", getCurrentDay()));
        } catch (ParseException e) {
            PrintException.print(e);
        }
        return null;
    }
}
